/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef GIMI_DATATYPEDESCRIPTIONS_H
#define GIMI_DATATYPEDESCRIPTIONS_H

/**
 * \todo All this kind of data should be read from XML or other conf file instead of hardcoding!!!!
 *
 */

#include <string>
#include <map>

#include <cassert>

#include "gimutils.h"
#include "gimiprotocoltypes.h"

namespace gimi {

struct DataTypeDefinition {
  DataTypeDefinition();
  DataTypeDefinition(const int typeId,
                      const std::string &typeName,
                      const std::string &typeDescription);
  ~DataTypeDefinition();
  
  int dataTypeId;
  std::string dataTypeName;
  std::string dataTypeDescription;
};

typedef std::map< int, DataTypeDefinition > t_datatypeMap;
typedef t_datatypeMap::iterator t_datatypeMapIterator;
typedef t_datatypeMap::const_iterator t_datatypeMapConstIterator;
typedef std::pair< int, DataTypeDefinition > t_datatypeMapPair;

class DataTypeDefinitions {
  public:
    DataTypeDefinitions()
      : typeMap(),
        definitionMutex (ownMutex_Init()) {
          assert(definitionMutex != NULL);
//// Insert datatype descriptions here !! /////////////////////////////////////

addDefinition(GIMI_PROTOCOL_CLIENT_DESCRIPTION,
              "GIMI_CLIENT_DESCRIPTION",
              "Internal datatype for sending clients description-information");

addDefinition(GIMI_PROTOCOL_GIMI_HUB_STATUS,
              "GIMI_HUB_STATUS",
              "Datatype for arrived hub-statusmessages.");

addDefinition(GIMI_PROTOCOL_AVANT_REPLY_V3,
              "AVANT_REPLY_V3",
              "Replydata produced by Avant");

addDefinition(GIMI_PROTOCOL_AVANT_CMD_V3,
              "AVANT_CMD_V3",
              "Avant's command data.");

addDefinition(GIMI_PROTOCOL_JPEG_WITH_TIMESTAMP,
              "JPEG_WITH_TIMESTAMP",
              "Jpeg-images with timestamp");

addDefinition(GIMI_PROTOCOL_UDPFW_FRAME,
              "UDPFW_FRAME",
              "UDP forwarder frame");

addDefinition(GIMI_PROTOCOL_AVANTSIMULATORSTATE_V1,
              "AVANTSIMULATORSTATE_V1",
              "Avant Simulator state");

addDefinition(GIMI_PROTOCOL_BITMAP_WITH_TIMESTAMP,
              "BITMAP_WITH_TIMESTAMP",
              "Bitmap data format");

addDefinition(GIMI_PROTOCOL_AUDIO_PCM,
              "AUDIO_PCM",
              "PCM audio (raw uncompressed)");

addDefinition(GIMI_PROTOCOL_AVANT_SIMCMD,
              "AVANT_SIMCMD",
              "Avant Simulator command format");

addDefinition(GIMI_PROTOCOL_GIMNOTIFIER_MESSAGE,
              "GIMNOTIFIER_MESSAGE",
              "GIMNotifier message");

addDefinition(GIMI_PROTOCOL_IMAGESERVER_CTRL,
              "IMAGESERVER_CTRL",
              "Imageserver control package");

addDefinition(GIMI_PROTOCOL_BITMAP_NET_VECTOR,
              "BITMAP_NET_VECTOR",
              "Many bitmap images combined to one");

addDefinition(GIMI_PROTOCOL_COORD2D,
              "COORD2D",
              "(x,y)-coordinate pair");

addDefinition(GIMI_PROTOCOL_PTU_POSITION_COMMAND,
              "PTU_POSITION_COMMAND",
              "J2B2 PTU Command");

addDefinition(GIMI_PROTOCOL_GIMDB,
              "GIMDB",
              "GIMdb data");

addDefinition(GIMI_PROTOCOL_FSR09ERPCOMM,
	      "FSR09ERP",
	      "FSR09 Course ERP system communication protocol");

addDefinition(GIMI_PROTOCOL_SERIALLINK,
	      "SerialLink",
	      "Communication protocol for creating a virtual Serial port over GIMnet");

addDefinition(GIMI_PROTOCOL_ASROBO_CMD_RANGING,
              "ASROBO_CMD_RANGING",
              "Ranging Command");

addDefinition(GIMI_PROTOCOL_ASROBO_CMD_POSITION,
              "ASROBO_CMD_POSITION",
              "Position Command");

addDefinition(GIMI_PROTOCOL_ASROBO_CMD_LOCALIZE,
              "ASROBO_CMD_LOCALIZE",
              "Localize Command");

addDefinition(GIMI_PROTOCOL_ASROBO_CMD_IO,
              "ASROBO_CMD_IO",
              "IO Command");

addDefinition(GIMI_PROTOCOL_ASROBO_CMD_CTRL_DRIVE2D,
              "ASROBO_CMD_CTRL_DRIVE2D",
              "Ctrl::Drive2D command");

addDefinition(GIMI_PROTOCOL_ASROBO_EVENT_POSITION_ODOMETRY,
              "ASROBO_EVENT_POSITION_ODOMETRY",
              "Position::Odometry event");

addDefinition(GIMI_PROTOCOL_ASROBO_EVENT_RANGING_DISTANCEARRAY,
              "ASROBO_EVENT_RANGING_DISTANCEARRAY",
              "Ranging::DistanceArray event");

///////////////////////////////////////////////////////////////////////////////
// MaCI Services Begin ---> 
//
// NOTE: All MaCI Service names must be formatted like:
// 'MaCI_<interfacename>'. This is because the name field is used and
// automatically processed by 'MaCI Automatic Service Discovery'
addDefinition(GIMI_PROTOCOL_MACI_MACICTRL,
	      "MaCI_MaCICtrl",
	      "MaCI Control Interface");

addDefinition(GIMI_PROTOCOL_MACI_RANGING,
	      "MaCI_Ranging",
	      "MaCI Ranging Interface");

addDefinition(GIMI_PROTOCOL_MACI_SPEEDCTRL,
	      "MaCI_SpeedCtrl",
	      "MaCI Speed Control Interface");

addDefinition(GIMI_PROTOCOL_MACI_TEXT,
	      "MaCI_Text",
	      "MaCI Text Interface");

addDefinition(GIMI_PROTOCOL_MACI_IMAGE,
	      "MaCI_Image",
	      "MaCI Image Interface");

addDefinition(GIMI_PROTOCOL_MACI_POSITION,
	      "MaCI_Position",
	      "MaCI Position Interface");

addDefinition(GIMI_PROTOCOL_MACI_IO,
	      "MaCI_IO",
	      "MaCI IO Interface");

addDefinition(GIMI_PROTOCOL_MACI_COORDINATEDRIVE,
	      "MaCI_CoordinateDrive",
	      "MaCI CoordinateDrive Interface");

addDefinition(GIMI_PROTOCOL_MACI_JOINTGROUPCTRL,
              "MaCI_JointGroupCtrl",
              "MaCI Joint Group Control Interface");
 
addDefinition(GIMI_PROTOCOL_MACI_MAP,
              "MaCI_Map",
              "MaCI Map Interface");
 
addDefinition(GIMI_PROTOCOL_MACI_BEHAVIOUR,
              "MaCI_Behaviour",
              "MaCI Behaviour Interface");

addDefinition(GIMI_PROTOCOL_MACI_ALARM,
              "MaCI_Alarm",
              "MaCI Alarm Interface");

addDefinition(GIMI_PROTOCOL_MACI_BATTERY,
              "MaCI_Battery",
              "MaCI Battery Interface");

addDefinition(GIMI_PROTOCOL_MACI_IMU,
              "MaCI_IMU",
              "MaCI IMU Interface");

addDefinition(GIMI_PROTOCOL_MACI_DUMMY,
              "MaCI_Dummy",
              "MaCI Dummy Interface - This really does nothing.");

addDefinition(GIMI_PROTOCOL_MACI_WIRELESS,
              "MaCI_Wireless",
              "MaCI Wireless Interface");

addDefinition(GIMI_PROTOCOL_MACI_AUCTION,
              "MaCI_Auction",
              "MaCI Auction Interface");

addDefinition(GIMI_PROTOCOL_MACI_ENERGY,
              "MaCI_Energy",
              "MaCI Energy Interface");


addDefinition(GIMI_PROTOCOL_MACI_ENVIRONMENTMEASUREMENT,
              "MaCI_Environment_measurement",
              "MaCI Environment measurement interface");


addDefinition(GIMI_PROTOCOL_MACI_RECHARGER,
              "MaCI_Recharger",
              "MaCI Recharger Interface");

addDefinition(GIMI_PROTOCOL_MACI_TASKCTRL,
              "MaCI_TaskCtrl",
              "MaCI Task Control Interface (Task & MicroTask)");

addDefinition(GIMI_PROTOCOL_MACI_SQL,
              "MaCI_SQL",
              "MaCI SQL Interface");

addDefinition(GIMI_PROTOCOL_MACI_OBJECTDB,
              "MaCI_ObjectDB",
              "MaCI ObjectDatabase Interface");

addDefinition(GIMI_PROTOCOL_MACI_PARAMETER,
              "MaCI_Parameter",
              "MaCI Parameter Interface");

addDefinition(GIMI_PROTOCOL_MACI_AUDIO,
	      "MaCI_Audio",
	      "MaCI Audio Interface");

addDefinition(GIMI_PROTOCOL_MACI_EMERGENCYSTOP,
	      "MaCI_EmergencyStop",
	      "MaCI Emergency Stop Interface");

addDefinition(GIMI_PROTOCOL_MACI_BEARING,
	      "MaCI_Bearing",
	      "MaCI Bearing Interface");
        
addDefinition(GIMI_PROTOCOL_MACI_GIMBO,
              "MaCI_Gimbo",
              "MaCI Gimbo Interface");

addDefinition(GIMI_PROTOCOL_MACI_UNIT,
              "MaCI_Unit",
              "MaCI Unit Interface");
// MaCI Services End <---
///////////////////////////////////////////////////////////////////////////////

addDefinition(GIMI_PROTOCOL_TEXT,
              "GIMI_PROTOCOL_TEXT",
              "String/text stream");

addDefinition(GIMI_PROTOCOL_GIMBOCTRL,
              "GIMI_PROTOCOL_GIMBOCTRL",
              "Gimbo component control");

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
      }
      
    ~DataTypeDefinitions();

    /**
     * Adds a new datatype-definition.
     *
     * \param[in] typeId TypeId of the datatype.
     * \param[in] typeName Name of the datatype.
     * \param[in] typeDescription Description for the datatype.
     * \return True if definition added. False if definition already existed.
     */
    bool addDefinition(const int typeId,
                       const std::string &typeName,
                       const std::string &typeDescription);

    /**
     * Returns name of the specified datatype.
     *
     * \param[out] typeName Where name of the datatype will be written.
     * Empty string written if datatype not found.
     * \param[in] typeId Datatypeid
     * \return True if datatype found, false if not.
     */
    bool getDatatypeName(std::string& typeName,
                         const int typeId);

    /**
     * Returns description of the specified datatype.
     *
     * \param[out] typeDescription Where description of the datatype will
     * be written. Empty string written if datatype not found.
     * \param[in] typeId Datatypeid
     * \return True if datatype found, false if not.
     */
    bool getDatatypeDescription(std::string& typeDescription,
                                const int typeId);

    /**
     * Returns complete description of specified datatype containing it's
     * typeid, name and description.
     *
     * \param[out] definition Where the definition will be
     * written. Empty written if datatype not found.
     * \param[in] typeId Datatypeid
     * \return True if datatype found, false if not.
     */
    bool getDatatype(DataTypeDefinition& definition,
                     const int typeId);
    
  private:
    // Prevent copy constructors.
    DataTypeDefinitions(const DataTypeDefinitions& right);
    const DataTypeDefinitions& operator= (const DataTypeDefinitions& right);
    
    t_datatypeMap typeMap;
    ownMutexHandle definitionMutex;
};
  
} // end namespace gimi

#endif // GIMI_DATATYPEDESCRIPTIONS_H
